#pragma once
#include <unordered_map>
#include "Epoller.hpp"
#include "Connection.hpp"

using namespace EpollerModule;
// 将一堆的connection进行管理起来
const static int maxevents = 64;
#define BLOCK_WAIT -1

class TcpServer
{
public:
    TcpServer() : _isrunning(false), _timeout(BLOCK_WAIT)
    {
        _epoller.InitEpoller();
    }
    bool IsConnectionExists(int sockfd)
    {
        auto iter = _connections.find(sockfd);
        if (iter == _connections.end())
            return false;
        else
            return true;
    }

    // 将每一个连接添加进来，然后管理起来
    void AddConnnection(Connection *conn)
    {
        if (!conn)
            return;
        if (IsConnectionExists(conn->Sockfd()))
            return;
        // 1.TcpServer unordered_map
        _connections[conn->Sockfd()] = conn;
        lg.LogMessage(Info, "add connection success, sockfd: %d\n", conn->Sockfd());

        // 2.将指定的sockfd放入到epoller中管理起来
        _epoller.AddEvents(conn->Sockfd(), conn->Events());
    }

    void RemoveConnection(int sockfd)
    {
        if (!IsConnectionExists(sockfd))
            return;
        // 1.清理connections自己关心的事件
        _connections[sockfd]->SetEvents(0);
        // 2.清理epoller中对sockfd的关心
        _epoller.DelEvents(sockfd);
        // 3.移除connections中的key value
        _connections.erase(sockfd);
    }

    // 事件派发
    void LoopOnce(int timeout)
    {
        int n = _epoller.Wait(revs, maxevents, timeout);
        for (int i = 0; i < n; i++)
        {
            // 判断是什么事件就绪了
            int sockfd = revs[i].data.fd;
            uint32_t events = revs[i].events;

            // 将所有epoll检测到的fd问题，最后统一转化为读写问题
            if (events & EPOLLERR)
                events | (EPOLLIN | EPOLLOUT);
            if (events & EPOLLHUP)
                events | (EPOLLIN | EPOLLOUT);

            // 未来所有的IO操作都会转换为下面的问题
            // 整个代码有没有执行IO操作呢？ 并没有！
            // IO代码在哪里呢？ 在connection的回调函数中
            // 现在的整个代码做的是  事件派发
            if (events & EPOLLIN && IsConnectionExists(sockfd))
            {
                // 该方法在connect中被注册了，才能进行调用
                if (_connections[sockfd]->_recver)
                    _connections[sockfd]->_recver(_connections[sockfd]);
            }
            if (events & EPOLLOUT && IsConnectionExists(sockfd))
            {
                if (_connections[sockfd]->_sender)
                    _connections[sockfd]->_sender(_connections[sockfd]);
            }
        }
    }

    void EnableReadWrite(int sockfd, bool readable, bool writeable)
    {
        // 判断sockfd是否合法
        if (!IsConnectionExists(sockfd))
            return;
        uint32_t events = ((readable ? EPOLLIN : 0) | (writeable ? EPOLLOUT : 0) | EPOLLET);
        // 1.修改connection自己关心的事件
        _connections[sockfd]->SetEvents(events);
        // 2.在epoller中修改关心的事件，写透到内核
        _epoller.ModEvents(sockfd, events);
    }

    Epoller GetEpoller()
    {
        return _epoller;
    }

    void Dispatcher() // 派发
    {
        _isrunning = true;
        while (_isrunning)
        {
            _epoller.PrintListfd();
            LoopOnce(_timeout);
        }
        _isrunning = false;
    }
    ~TcpServer()
    {
    }

private:
    Epoller _epoller;
    std::unordered_map<int, Connection *> _connections;

    struct epoll_event revs[maxevents];

    bool _isrunning;
    int _timeout;
};